﻿@using System.Net.Http.Json
@using Microsoft.Extensions.Logging
@using System.Text.Json
@using static Masa.Auth.Contracts.Admin.UserClaimValuesDto
@inherits AdminCompontentBase
@inject HttpClient HttpClient
@inject ILogger<UserClaimsDialog> Logger

<DefaultSheetDialog @bind-Value="_visible" Title="@T("Claim")">
    <MForm>
        <AutoHeight Overflow>
            <AutoHeightContent>
                <MRow Class="py-4">
                    <MCol Md="6">
                        <SAutoComplete @bind-Value="@_claimKey" Required
                                       Label="@T("Type")"
                                       Items="@_claims"
                                       ItemText="@(u => $"{u.Name}({u.Description})")"
                                       ItemValue="u => u.Name"
                                       TItem="UserClaimSelectDto"
                                       TValue="string"
                                       TItemValue="string"
                                       OnSelect="OnClaimSelected">
                        </SAutoComplete>
                    </MCol>
                    <MCol Md="6">
                        @if (_claims.Any(x => x.Name == _claimKey && x.DataSourceType != DataSourceTypes.None))
                        {
                            <SAutoComplete @bind-Value="@_claimValues" Required Multiple
                                           Label="@T("Value")"
                                           Items="_sourceItems"
                                           ItemText="u => u.Text"
                                           ItemValue="u => u.Value">
                            </SAutoComplete>
                        }
                        else
                        {
                            <STextField Label="@T("Value")" @bind-Value="@_claimValue" Required />
                        }
                    </MCol>
                    <MCol Md="12">
                        <SButton Block OnClick="AddClaim">
                            <SIcon Left>
                                @IconConstants.Add
                            </SIcon>
                            @T("Add Claim")
                        </SButton>
                    </MCol>
                    @foreach (var _claimValue in _userClaimValues)
                    {
                        <MCol Md="12">
                            <STextField Value="@_claimValue.Value" ValueChanged="v=> ValueChanged(_claimValue,v)" TValue="string" Class="claim-value">
                                <PrependInnerContent>
                                    <span>
                                        @_claimValue.Key
                                    </span>
                                    @if (_claims.Any(x => x.Name == _claimValue.Key))
                                    {
                                        <span>
                                            (@(_claims.Find(x => x.Name == _claimValue.Key)?.Description))
                                        </span>
                                    }
                                </PrependInnerContent>
                                <AppendOuterContent>
                                    <MButton OnClick="()=>RemoveItem(_userClaimValues.IndexOf(_claimValue))">
                                        <SIcon Color="error">@IconConstants.Remove</SIcon>
                                    </MButton>
                                </AppendOuterContent>
                            </STextField>
                        </MCol>
                    }
                </MRow>
            </AutoHeightContent>
            <FooterContent>
                <div class="d-flex mt-6">
                    <MSpacer></MSpacer>
                    <SButton Medium OnClick="Save">@T("Save")</SButton>
                </div>
            </FooterContent>
        </AutoHeight>
    </MForm>
</DefaultSheetDialog>

@code {

    class DataSourceItemDto
    {
        public string Text { get; set; } = "";

        public string Value { get; set; } = "";
    }

    private List<UserClaimSelectDto> _claims = new();
    private string _claimKey = "", _claimValue = "";
    private List<string> _claimValues = new();
    private List<ClaimValue> _userClaimValues = new();
    private List<DataSourceItemDto> _sourceItems = new();
    private bool _visible;
    private Guid _userId;

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender)
        {
            _claims = await AuthCaller.UserClaimService.GetSelectAsync();
            StateHasChanged();
        }
        await base.OnAfterRenderAsync(firstRender);
    }

    private async Task OnClaimSelected((UserClaimSelectDto selectedClaim, bool selected) args)
    {
        _sourceItems = await GetDataSourceItems(args);
        StateHasChanged();
    }

    private async Task<List<DataSourceItemDto>> GetDataSourceItems((UserClaimSelectDto selectedClaim, bool selected) args)
    {
        if (!args.selected)
        {
            return new();
        }
        var claim = _claims.Find(x => x.Name == args.selectedClaim.Name);
        if (claim == null || claim.DataSourceType == DataSourceTypes.None) return new();

        try
        {
            var options = new JsonSerializerOptions
                {
                    PropertyNameCaseInsensitive = true
                };
            switch (claim.DataSourceType)
            {
                case DataSourceTypes.FixedJson:
                    if (!string.IsNullOrEmpty(claim.DataSourceValue))
                    {
                        return JsonSerializer.Deserialize<List<DataSourceItemDto>>(claim.DataSourceValue, options) ?? new();
                    }
                    break;
                case DataSourceTypes.Api:
                    if (!string.IsNullOrEmpty(claim.DataSourceValue))
                    {
                        var response = await HttpClient.GetFromJsonAsync<List<DataSourceItemDto>>(claim.DataSourceValue, options: options);
                        return response ?? new();
                    }
                    break;
            }
        }
        catch (Exception ex)
        {
            Logger.LogError(ex, "GetDataSourceItems error: {Message}", ex.Message);
        }

        return new List<DataSourceItemDto>();
    }

    public async Task ShowAsync(Guid userId)
    {
        _userId = userId;
        _userClaimValues = await AuthCaller.UserService.GetClaimValuesAsync(_userId);
        _visible = true;
        StateHasChanged();
    }

    void ValueChanged(ClaimValue item, string v)
    {
        item.Value = v;
    }

    public void RemoveItem(int index)
    {
        _userClaimValues.RemoveAt(index);
    }

    async Task Save()
    {
        await AuthCaller.UserService.SaveClaimValuesAsync(new UserClaimValuesDto
            {
                UserId = _userId,
                ClaimValues = _userClaimValues
            });
        Hidden();
    }

    void Cancel()
    {
        Hidden();
    }

    void Hidden()
    {
        _visible = false;
        _claimKey = "";
        _claimValue = "";
        _claimValues.Clear();
        _userClaimValues = new();
    }

    async Task AddClaim()
    {
        if (_claimKey.IsNullOrEmpty())
        {
            return;
        }

        if (_claims.Any(x => x.Name == _claimKey && x.DataSourceType == DataSourceTypes.None))
        {
            if (_claimValue.IsNullOrEmpty())
            {
                return;
            }
            if (_userClaimValues.Any(c => c.Key == _claimKey && c.Value == _claimValue))
            {
                await PopupService.EnqueueSnackbarAsync(T("RepeatAdd"), AlertTypes.Warning);
                return;
            }
            _userClaimValues.Add(new ClaimValue(_claimKey, _claimValue));
            _claimValue = "";
        }
        else
        {
            if (!_claimValues.Any())
            {
                return;
            }
            var newValues = _claimValues.Where(c => !_userClaimValues.Any(uc => uc.Key == _claimKey && uc.Value == c));
            _userClaimValues.AddRange(newValues.Select(c => new ClaimValue(_claimKey, c)));
            _claimValues.Clear();
        }

        _claimKey = "";
    }
}
